package com.life.ai.server.modules.system.service.impl;

import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.life.ai.server.common.constants.Constants;
import com.life.ai.server.common.constants.UserConstants;
import com.life.ai.server.common.domain.PageQuery;
import com.life.ai.server.framework.redis.annotation.RedisCache;
import com.life.ai.server.framework.redis.annotation.RedisEvict;
import com.life.ai.server.modules.system.entity.SysMenu;
import com.life.ai.server.modules.system.entity.SysRole;
import com.life.ai.server.modules.system.entity.SysUserRole;
import com.life.ai.server.modules.system.enums.RoleStatusEnum;
import com.life.ai.server.modules.system.mapper.SysUserRoleMapper;
import com.life.ai.server.modules.system.service.SysRoleMenuService;
import com.life.ai.server.modules.system.service.SysRoleService;
import com.life.ai.server.modules.system.service.SysUserRoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 用户和角色关联表 服务实现类
 * </p>
 *
 * @author kylewka
 * @since 2024-06-11
 */
@Service
public class SysUserRoleServiceImpl extends ServiceImpl<SysUserRoleMapper, SysUserRole> implements SysUserRoleService, StpInterface {

    @Resource
    private SysRoleService roleService;
    @Resource
    private SysUserRoleService userRoleService;
    @Resource
    private SysRoleMenuService roleMenuService;

    /**
     * 返回指定账号id所拥有的权限码集合
     *
     * @param loginId   账号id
     * @param loginType 账号类型
     * @return 该账号id具有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        // 根据用户id获取角色列表
        List<SysRole> roles = userRoleService.listByUserId(Long.valueOf(loginId.toString()));
        // 超级管理员赋予全部权限
        if (roles.stream().anyMatch(role -> Constants.SUPER_ADMIN.equals(role.getCode()))) {
            return CollUtil.toList("*");
        }
        // 根据角色列表获取权限列表
        List<Long> roleIds = CollStreamUtil.toList(roles, SysRole::getId);
        List<SysMenu> sysMenus = roleMenuService.listByRoleIds(roleIds);
        return CollStreamUtil.toList(sysMenus, SysMenu::getPermission);
    }

    /**
     * 返回指定账号id所拥有的角色标识集合
     *
     * @param loginId   账号id
     * @param loginType 账号类型
     * @return 该账号id具有的角色标识集合
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        // 根据用户id获取角色列表
        List<SysRole> roles = userRoleService.listByUserId(Long.valueOf(loginId.toString()));
        if (roles.stream().anyMatch(role -> Constants.SUPER_ADMIN.equals(role.getCode()))) {
            return CollUtil.toList("*");
        }
        return CollStreamUtil.toList(roles, SysRole::getCode);
    }

    /**
     * 分页查询
     *
     * @param pageQuery   分页参数
     * @param sysUserRole 查询条件
     * @return Page<SysUserRole>
     */
    @Override
    public Page<SysUserRole> queryPage(PageQuery pageQuery, SysUserRole sysUserRole) {
        return lambdaQuery().page(pageQuery.build());
    }

    /**
     * 根据用户id查询角色列表
     *
     * @param userId 用户id
     * @return List<SysRole>
     */
    @RedisCache(name = UserConstants.SYS_ROLE_OF_USER, keys = "#userId")
    @Override
    public List<SysRole> listByUserId(Long userId) {
        List<SysUserRole> roles = lambdaQuery().eq(SysUserRole::getUserId, userId).list();
        if (CollUtil.isEmpty(roles)) {
            return new ArrayList<>();
        }
        List<Long> roleIds = CollStreamUtil.toList(roles, SysUserRole::getRoleId);
        return roleService.lambdaQuery().eq(SysRole::getStatus, RoleStatusEnum.NORMAL.getCode())
                .in(SysRole::getId, roleIds).list();
    }

    /**
     * 修改用户角色
     *
     * @param userId  用户id
     * @param roleIds 角色id集合
     */
    @RedisEvict(name = UserConstants.SYS_ROLE_OF_USER, keys = "#userId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserRole(Long userId, List<Long> roleIds) {
        // 移除旧的角色列表
        lambdaUpdate().eq(SysUserRole::getUserId, userId).remove();
        // 保存新的角色列表
        List<SysUserRole> sysUserRoles = CollStreamUtil.toList(roleIds,
                roleId -> new SysUserRole().setUserId(userId).setRoleId(roleId));
        this.saveBatch(sysUserRoles);
    }

    /**
     * 移除用户关联角色
     *
     * @param userId 用户id
     */
    @RedisEvict(name = UserConstants.SYS_ROLE_OF_USER, keys = "#userId")
    @Override
    public void removeByUserId(Long userId) {
        this.lambdaUpdate().eq(SysUserRole::getUserId, userId).remove();
    }
}

